package common

import (
	"encoding/binary"
	"encoding/json"
	"fmt"
	"io"
	"net"
)

const (
	cmdPP        = 0x0
	cmdHandshake = 0x1
)

// ProxyProtocol 私有协议
type ProxyProtocol struct {
	ClientId   string `json:"clientId"`
	ListenIp   string `json:"listenIp"`
	ListenPort uint16 `json:"listenPort"`
	TargetIP   string `json:"targetIP"`
	TargetPort uint16 `json:"targetPort"`
}

// 简单的私有协议
// 1byte version
// 1byte cmd
// 2byte lentth

func (pp *ProxyProtocol) Encode() ([]byte, error) {
	hdr := make([]byte, 4)
	hdr[0] = 0x0
	hdr[1] = 0x0
	// 使用JSON序列化
	body, err := json.Marshal(pp)
	if err != nil {
		return nil, err
	}
	binary.BigEndian.PutUint16(hdr[2:4], uint16(len(body)))
	return append(hdr, body...), nil
}

func (pp *ProxyProtocol) Decode(reader io.Reader) error {
	hdr := make([]byte, 4)
	// 读取四个字节的数据
	_, err := io.ReadFull(reader, hdr)
	if err != nil {
		return err
	}
	if hdr[1] != cmdPP {
		return fmt.Errorf("invalid handshake cmd")
	}

	bodyLen := binary.BigEndian.Uint16(hdr[2:4])
	body := make([]byte, bodyLen)
	// 读取body
	_, err = io.ReadFull(reader, body)
	if err != nil {
		return err
	}
	err = json.Unmarshal(body, pp)
	if err != nil {
		return err
	}
	return nil
}

type HandshakeReq struct {
	ClientId string `json:"clientId"`
}

func (req *HandshakeReq) Encode() ([]byte, error) {
	hdr := make([]byte, 4)
	hdr[0] = 0x0
	hdr[1] = cmdHandshake
	// 使用JSON序列化
	body, err := json.Marshal(req)
	if err != nil {
		return nil, err
	}
	// 将body长度插入(uint16需要2个字节)
	binary.BigEndian.PutUint16(hdr[2:4], uint16(len(body)))
	return append(hdr, body...), nil
}

func (req *HandshakeReq) Decode(reader net.Conn) error {
	hdr := make([]byte, 4)
	_, err := io.ReadFull(reader, hdr)
	if err != nil {
		return err
	}
	if hdr[1] != cmdHandshake {
		return fmt.Errorf("invalid handshake cmd")
	}
	bodyLen := binary.BigEndian.Uint16(hdr[2:4])
	body := make([]byte, bodyLen)
	// 读取 body
	_, err = io.ReadFull(reader, body)
	if err != nil {
		return err
	}
	// 解析JSON
	err = json.Unmarshal(body, req)
	if err != nil {
		return err
	}
	return nil
}
